package com.xxdemo.quickstart;

import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

import static com.xxdemo.quickstart.SqlInjectionCheckingTool.safeTokenFromUnsafe;

@Service
public class CustomerRecordMaintainingService {

    /// 限制单次查询最大允许返回多少行结果, 尽量减轻数据库的查询压力
    private static final int MAX_RECORDS_OF_SEARCH_OPERATION = 500;
    public static int maxRecordsPerPage() {
        // 单次查询最多返回多少行查询结果
        return MAX_RECORDS_OF_SEARCH_OPERATION;
    }

    private final CustomerMapper _customerMapper;

    public CustomerRecordMaintainingService(CustomerMapper customerMapper) {
        this._customerMapper = customerMapper;
    }

    public Optional<Customer> findCustomerById(Long id){
        return _customerMapper.findById(id);
    }

    public List<Customer> findCustomerByNameContains(String unsafeNameSearchToken){
        QuerySettings settings =
                new GenericQuerySettings(MAX_RECORDS_OF_SEARCH_OPERATION);
        return findCustomerByNameContains(unsafeNameSearchToken, settings);
    }

    public List<Customer> findCustomerByNameContains(String unsafeNameSearchToken, QuerySettings settings){
        String safeToken = safeTokenFromUnsafe(unsafeNameSearchToken);
        return _customerMapper.findCustomersByNameContains(safeToken, settings.getSortBy(), settings.getOrderIsDesc(), settings.getLimit());
    }

    public List<Customer> findAll() {
        QuerySettings settings =
                new GenericQuerySettings(MAX_RECORDS_OF_SEARCH_OPERATION);
        return findAll(settings);
    }

    public List<Customer> findAll(QuerySettings settings) {
        return _customerMapper.findCustomersByNameContains(null, settings.getSortBy(), settings.getOrderIsDesc(), settings.getLimit());
    }

    public List<Customer> findByIdWithinRange(CustomerIdNumberRange range, int topN) {
        if (topN <= 0 || topN > MAX_RECORDS_OF_SEARCH_OPERATION) {
            topN = MAX_RECORDS_OF_SEARCH_OPERATION;
        }
        Long idFirst = range.rangeStart();
        Long idLast = idFirst + range.rangeWidth() - 1;
        return _customerMapper.findByIdRangeInclusive(idFirst, idLast, topN);
    }

    public List<Customer> findByIdWithinRange(CustomerIdNumberRange range) {
        return findByIdWithinRange(range, MAX_RECORDS_OF_SEARCH_OPERATION);
    }

    public List<Customer> listCustomerIdGreaterThan(long prevCustomerId, int topN) {
        if (topN <= 0 || topN > MAX_RECORDS_OF_SEARCH_OPERATION) {
            topN = MAX_RECORDS_OF_SEARCH_OPERATION;
        }
        return _customerMapper.findCustomersWithCustomerIdGreaterThan(prevCustomerId, topN);
    }
}
